#define _GNU_SOURCE
#include "Buffer.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/uio.h>
#include <sys/types.h>
#include <sys/socket.h>

struct Buffer *bufferInit(int32_t size)
{
    struct Buffer *buffer = (struct Buffer *)malloc(sizeof(struct Buffer));
    if (buffer != NULL)
    {
        buffer->data = (char *)calloc(size, sizeof(char));
        if (buffer->data == NULL)
        {
            return NULL;
        }
        buffer->capacity = size;
        buffer->readPos = buffer->writePos = 0;
    }

    return buffer;
}

void bufferDestroy(struct Buffer *buffer)
{
    if (buffer != NULL)
    {
        if (buffer->data != NULL)
        {
            free(buffer->data);
        }
        free(buffer);
    }
}

void bufferExtendRoom(struct Buffer *buffer, int32_t size)
{
    // 1.内存够用 - 不需要扩容
    if (bufferWriteableSize(buffer) >= size)
    {
        return;
    }
    // 2.内存需要合并才够用 - 不需要扩容
    // 剩余的可写的内存 + 已读的内存 > size
    if (buffer->readPos + bufferWriteableSize(buffer) >= size)
    {
        // 得到未读的内存大小
        int32_t readable = bufferReadableSize(buffer);
        // 移动内存
        memcpy(buffer->data, buffer->readPos + buffer->data, readable);
        // 更新位置
        buffer->readPos = 0;
        buffer->writePos = readable;
    }
    // 3.内存不够用 - 扩容
    else
    {
        void *temp = realloc(buffer->data, buffer->capacity + size);
        if (temp == NULL)
        {
            return;
        }
        memset(temp + buffer->capacity, 0, size);
        // 更新数据
        buffer->data = temp;
        buffer->capacity += size;
    }
}

int32_t bufferWriteableSize(struct Buffer *buffer)
{
    return buffer->capacity - buffer->writePos;
}

int32_t bufferReadableSize(struct Buffer *buffer)
{
    return buffer->writePos - buffer->readPos;
}

int8_t bufferAppendData(struct Buffer *buffer, const char *data, int32_t size)
{
    if (buffer == NULL || data == NULL || size <= 0)
    {
        return -1;
    }
    // 扩容
    bufferExtendRoom(buffer, size);
    // 数据拷贝
    memcpy(buffer->data + buffer->writePos, data, size);
    buffer->writePos += size;
    return 0;
}

int8_t bufferAppendString(struct Buffer *buffer, const char *data)
{
    int32_t size = strlen(data);
    bufferAppendData(buffer, data, size);
    return 0;
}

int32_t bufferSocketRead(struct Buffer *buffer, int32_t fd)
{
    // read/recv/readv
    struct iovec vec[2];
    // 初始化数据元素
    int32_t writeable = bufferWriteableSize(buffer);
    vec[0].iov_base = buffer->data + buffer->writePos;
    vec[0].iov_len = writeable;
    char *tmpBuff = (char *)malloc(40960);
    vec[1].iov_base = tmpBuff;
    vec[1].iov_len = 40960;
    int32_t result = readv(fd, vec, 2);
    if (result == -1)
    {
        return -1;
    }
    else if (result <= writeable)
    {
        buffer->writePos += result;
    }
    else
    {
        buffer->writePos = buffer->capacity;
        bufferAppendData(buffer, tmpBuff, result - writeable);
    }
    free(tmpBuff);
    return result;
}

char *bufferFindCRLF(struct Buffer *buffer)
{
    // strstr --> 大字符串中匹配子字符串(遇到\0结束)
    // memmem --> 大数据块中匹配子数据块(需要指定数据块大小)
    //  void *memmem(const void *haystack, size_t haystacklen,
    //               const void *needle, size_t needlelen);
    char *ptr = memmem(buffer->data + buffer->readPos, bufferReadableSize(buffer), "\r\n", 2);
    return ptr;
}

int32_t bufferSendData(struct Buffer *buffer, int32_t socket)
{
    // 判断有无数据
    int32_t readable = bufferReadableSize(buffer);
    if (readable > 0)
    {   
        int32_t count = send(socket, buffer->data + buffer->readPos, readable, MSG_NOSIGNAL);
        printf("已发送cfd = %d, %d 总共= %d\n", socket, count, readable);
        if (count)
        {
            buffer->readPos += count;
            usleep(1);
        }
        else if(count == -1)
        {
            return -1;
        }
        return count;
    }
    return 0;
}
